package com.projecy.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.projecy.common.constant.CommonConstants;
import com.projecy.common.exception.BadRequestException;
import com.projecy.common.utils.StringUtil;
import com.projecy.system.mapper.SysMenuMapper;
import com.projecy.system.mapper.SysRoleMenuMapper;
import com.projecy.system.model.SysMenu;
import com.projecy.system.model.SysRoleMenu;
import com.projecy.system.service.SysMenuService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class SysMenuServiceImpl implements SysMenuService {
    @Autowired
    SysMenuMapper menuMapper;
    @Autowired
    SysRoleMenuMapper roleMenuMapper;


    @Override//赋予功能
    public JSONArray getMenuTree(List<String> roles) {//获取菜单树
        System.out.println("获取菜单树(赋予功能)");
        Set<SysMenu> menuSet1 = new HashSet<>();
        try {
            List<SysMenu> menuListAll;
            //  如果角色中包含admin,则直接查询所有菜单
            if (roles.contains(CommonConstants.ROLE_ADMIN)){
                menuListAll = menuMapper.selectList(null);
                System.out.println("menuList超级管理员"+menuListAll);
            } else {

                menuListAll = menuMapper.getMenuTree(roles);
                //查询用户菜单权限
                if (!CollectionUtils.isEmpty(menuListAll)){
                    Set<SysMenu> menuSet = new HashSet<>();
//                    for (int i=1;i<=menuListAll.size();i++){
//                        System.out.println("sysMenu.getId()==========="+sysMenu.getId());
//                        menuSet.addAll(getAllMenusByChildId(sysMenu.getId()));
//                    }

//                    List newList =  menuListAll.stream().distinct().collect(Collectors.toList());
//                    System.out.println(newList.toString());
                    for (SysMenu sysMenu : menuListAll) {
                        System.out.println("sysMenu.getId()==========="+sysMenu.getId());
                        System.out.println("sysMenu==========="+sysMenu);
                        System.out.println("++++++++++++++"+getAllMenusByChildId(sysMenu.getId()));
                        menuSet.addAll(getAllMenusByChildId(sysMenu.getId()));
                        System.out.println("menuSet"+menuSet);

                        //menuSet.hashCode();//hashCode需要重写方法
//                        menuSet.forEach(System.out::println);
                    }

                    Object[] objects = menuSet.toArray();
                    for (int i = 0;i<objects.length;i++){
                        System.out.println("object"+objects[i]);
                    }
                    System.out.println("menuSetss"+menuSet);
//                    for (SysMenu sysMenu : menuListAll) {
//                        System.out.println("sss==========="+sysMenu.getId());
//                        System.out.println("sss==========="+sysMenu.getName());
//                        //menuSet.hashCode();//hashCode需要重写方法
////                        menuSet.forEach(System.out::println);
//                    }
                    //menuListAll = new ArrayList<>(menuListAll).stream().distinct().collect(Collectors.toList());
                    menuListAll = new ArrayList<>(menuSet).stream().distinct().collect(Collectors.toList());
                    System.out.println("menuListAll===================>"+menuListAll);
                }
            }
            return getObjects(menuListAll, 0l, "title", null);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public JSONArray getMenuSelectTree(String type) {//获取下拉框里面的树
        try {
            QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
            if (StringUtils.isNotBlank(type)){
                wrapper.eq("type", type);
            }
            List<SysMenu> menuList = menuMapper.selectList(wrapper);
            JSONArray jsonArray = new JSONArray();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", "0");
            jsonObject.put("name", "顶级目录");
            jsonObject.put("open", true);
            jsonObject.put("checked", false);
            if (!getObjects(menuList, 0l,  "name", null).isEmpty()){
                jsonObject.put("children", getObjects(menuList, 0l,  "name", null));
            }
            jsonArray.add(0, jsonObject);
            return jsonArray;
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public void editMenu(SysMenu sysMenu) {//编辑菜单
        try {
            if (sysMenu.getId() != null){
                menuMapper.updateById(sysMenu);
            } else {
                menuMapper.insert(sysMenu);
            }
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public void delMenu(Long id) {//删除菜单
        try {
            //  校验菜单是否已绑定角色
            checkMenuRole(id);
            menuMapper.deleteById(id);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }

    @Override
    public JSONArray getMenuTreeByRoleId(String roleId) {//获取角色菜单树
        try {
            //  当前角色菜单
            List<String> menuList = menuMapper.getMenuTreeByRoleId(roleId);
            //  所有菜单
            List<SysMenu> allMenuList = menuMapper.selectList(null);
            return getObjects(allMenuList, 0l, "title", menuList);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public List<SysMenu> queryAllMenus(List<String> roles) {//查询当前用户所有权限菜单
        try {

            //允许用户登录并将权限与CommonConstants类中定义的权限对比
            System.out.println("--------ROLE_ADMIN"+roles.contains(CommonConstants.ROLE_ADMIN));//
            if (roles.contains(CommonConstants.ROLE_ADMIN)){
                System.out.println("-----------------------------------------");
                System.out.println("--------ROLE_ADMIN"+roles.contains(CommonConstants.ROLE_ADMIN));//true
                return menuMapper.selectList(null);
            }
            if (roles.contains(CommonConstants.ROLE_USER)){
                System.out.println("-----------------------------------------");
                System.out.println("--------ROLE_USER"+roles.contains(CommonConstants.ROLE_USER));//true
                return menuMapper.selectList(null);
            }
            if (roles.contains(CommonConstants.ROLE_TEST)){
                System.out.println("-----------------------------------------");
                System.out.println("--------ROLE_TEST"+roles.contains(CommonConstants.ROLE_TEST));//true
                return menuMapper.selectList(null);
            }
            return menuMapper.getMenuTree(roles);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public JSONArray getMenuTable(String blurry) {//获取菜单列表
        try {
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            if (StringUtil.isNotBlank(blurry)){
                System.out.println("blurry==="+blurry);
                wrapper.like(SysMenu::getName, blurry);
                wrapper.or();
                wrapper.like(SysMenu::getPath, blurry);
            }
            wrapper.orderByAsc(SysMenu::getSort);
            List<SysMenu> list = menuMapper.selectList(wrapper);

            return getObjects(list, 0l, "title", null);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public List<String> getUrlsByRoles(List<String> roles) {//通过角色获取所有授权菜单
        try {
            return menuMapper.getMenuUrlByRole(roles);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    @Override
    public JSONArray getMenuTreeForLeft(List<String> roles) {//获取左侧菜单树
        //  如果是系统管理员，则直接获取所有菜单
        List<SysMenu> menuList = new ArrayList<>();
        System.out.println("系统管理员++");
        System.out.println("rolesssss"+roles);
        System.out.println(roles.contains(CommonConstants.ROLE_ADMIN));
        if (roles.contains(CommonConstants.ROLE_ADMIN)){
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            //  菜单
            wrapper.eq(SysMenu::getType, "1");
            wrapper.or();
            //  页面
            wrapper.eq(SysMenu::getType, "2");

            wrapper.orderByAsc(SysMenu::getSort);
            menuList = menuMapper.selectList(wrapper);
            System.out.println(menuList.size());
            System.out.println("menuList.toString()"+menuList.toString());
        }
        JSONArray jsonArray = new JSONArray();
        if (!CollectionUtils.isEmpty(menuList)){
            List<SysMenu> topMenuList = menuList.stream().filter(sysMenu -> sysMenu.getParentId() == 0L).collect(Collectors.toList());
            for (SysMenu sysMenu : topMenuList) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", sysMenu.getId());
                jsonObject.put("path", sysMenu.getPath());
                jsonObject.put("name", sysMenu.getName());
                jsonObject.put("type", sysMenu.getType());
                if (!CollectionUtils.isEmpty(getChildMenu(menuList, sysMenu.getId(), "left", null))){
                    jsonObject.put("children", getChildMenu(menuList, sysMenu.getId(), "left", null));
                }
                jsonArray.add(jsonObject);
            }
        }
        return jsonArray;
    }


    public JSONArray getChildMenu(List<SysMenu> menuListAll, Long id, String title, List<String> menuIds){//获取子菜单
        try {
//            for (SysMenu sysMenu : menuListAll) {
//                System.out.println("========s==="+sysMenu.getId());
//                System.out.println("========s==="+sysMenu.getName());
//            }
            return getObjects(menuListAll, id, title, menuIds);

        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    private JSONArray getObjects(List<SysMenu> menuListAll, Long id, String title, List<String> menuIds) {//组装树的公共方法
        try {
            //  获取子菜单(不包含按钮)
            List<SysMenu> childList = menuListAll.stream().filter(menu ->
                    menu.getParentId().longValue() == id.longValue() && !"3".equals(menu.getType())).collect(Collectors.toList());
            System.out.println("------childList-----------");
            System.out.println(childList.size());
            System.out.println(childList.toString());
            System.out.println("toArray");
            childList.stream().toArray();
            //  组装树
            JSONArray jsonArray = new JSONArray();
            childList.forEach(menu -> {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", menu.getId());
                jsonObject.put(title, menu.getName());

                if ("title".equals(title)){
//                    System.out.println("title: " + jsonObject.toString());
                    jsonObject.put("parentId", menu.getParentId());//父id
                    jsonObject.put("path", menu.getPath());//url
                    jsonObject.put("name", menu.getName());
                    jsonObject.put("type", menu.getType());//类型
                    jsonObject.put("sort", menu.getSort());
                    jsonObject.put("component", menu.getComponent());//组件
//                    jsonObject.put("permission", menu.getPermission());
                    if (!CollectionUtils.isEmpty(menuIds) && menuIds.contains(menu.getId().toString())){
                        jsonObject.put("checked", true);
                    }
                } else if ("name".equals(title)){
                    jsonObject.put("open", false);
                    jsonObject.put("checked", false);
                } else if ("left".equals(title)){
                    jsonObject.put("name", menu.getName());
                    jsonObject.put("path", menu.getPath());
                    jsonObject.put("type", menu.getType());
                }
                if (menuListAll.stream().anyMatch(menu1 -> menu1.getParentId().longValue() == id.longValue())) {
                    if (!getChildMenu(menuListAll, menu.getId(), title, menuIds).isEmpty()){
                        jsonObject.put("children", getChildMenu(menuListAll, menu.getId(), title, menuIds));
                    }
                }
                System.out.println("jsonObject========================"+jsonObject);
                jsonArray.add(jsonObject);
            });
            System.out.println("jsonArray: " + jsonArray.toString());
            return jsonArray;
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }


    private void checkMenuRole(Long menuId){//校验菜单是否已绑定角色
        try {
            LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysRoleMenu::getMenuId, menuId);
            long count = roleMenuMapper.selectCount(wrapper);
            if (count > 0){
                throw new BadRequestException("该菜单已绑定角色，无法删除");
            }
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }

    private List<SysMenu> getAllMenusByChildId(Long menuId){
        try {
            return menuMapper.getAllMenusByChildId(menuId);
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }
}
